﻿using ProyectoDeTesis.Modelos.Filtros;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using Telerik.WinControls.UI;

namespace ProyectoDeTesis.Controladores
{
    public class VueloController
    {
        private Random randNum = new Random();
        private FlightXML2 df = new FlightXML2();
        private PersonalController personalController = new PersonalController();

        public List<ScheduledFlightStruct> getScheduledFlights(string airport, int howMany) 
        {
            
            df.Credentials = new NetworkCredential("mariporras7", "9dddcd24fba2ced197605770c06d636d4cd41e09");
            df.PreAuthenticate = true;

            List<ScheduledFlightStruct> listScheduledFlights = new List<ScheduledFlightStruct>();
            try 
            {
                ScheduledStruct s = null;
                s = df.Scheduled(airport, df.SetMaximumResultSize(howMany), "", 0);
                listScheduledFlights.AddRange(s.scheduled.ToList());

            }
            catch (Exception e) 
            {
                Console.WriteLine(e.Message);
            }
            return listScheduledFlights;
        }

        public List<Vuelo> getVuelos(string airport, int howMany)
        {
            List<Vuelo> listaVuelos = new List<Vuelo>();
            List<ScheduledFlightStruct> listScheduledFlights = getScheduledFlights(airport, howMany);
            guardarVuelos(listScheduledFlights);

            DateTime hoy = DateTime.Now.Date.AddDays(1);

            var db = new Bd_tesisDataContext();
            var query = (from v in db.Vuelo
                         where v.fecha_salida.CompareTo(hoy) == 0
                         orderby v.fecha_salida descending, v.hora_salida descending
                         select v);

            listaVuelos = query.ToList();

            return listaVuelos;
        }

        private void guardarVuelos(List<ScheduledFlightStruct> listScheduledFlights)
        {
            var bd = new Bd_tesisDataContext();

            foreach (ScheduledFlightStruct scheduled in listScheduledFlights)
            {
                Vuelo v = new Vuelo();
                v.fecha_creacion = DateTime.Now;
                v.fecha_actualizacion = DateTime.Now;
                v.num_vuelo = scheduled.ident;
                DateTime fecha_hora_salida = UnixTimeStampToDateTime(scheduled.filed_departuretime);
                v.fecha_salida = fecha_hora_salida.Date;
                v.hora_salida = fecha_hora_salida.ToString("HH:mm");
                DateTime fecha_hora_llegada = UnixTimeStampToDateTime(scheduled.estimatedarrivaltime);
                v.fecha_llegada = fecha_hora_llegada.Date;
                v.hora_llegada = fecha_hora_llegada.ToString("HH:mm");
                v.nombre_aeropuerto = scheduled.destinationName;
                v.nombre_destino = scheduled.destinationCity;
                v.Tipo_avion = scheduled.aircrafttype;
                v.nombre_origen = "Lima";
                v.estado = "En Espera";
                v.tipo_vuelo = "Normal";
                v.num_pasajeros = calcular_pasajeros();
                //v.perfil_personal_id = 0;
                v.carga = calcular_carga(Convert.ToInt32(v.num_pasajeros));
                bd.Vuelo.InsertOnSubmit(v);
            }
            bd.SubmitChanges();
        }

        private int calcular_carga(int num_pasajeros)
        {
            int carga = 0;

            int probabilidad_0 = randNum.Next(11);
            int probabilidad_2amas = randNum.Next(16);
            int _2amas = randNum.Next(2,6);
            int probabilidad_1 = randNum.Next(100 - (probabilidad_0 + probabilidad_2amas) + 1);
            int probabilidad_2 = 100 - (probabilidad_0 + probabilidad_1 + probabilidad_2amas);

            carga = 1 * Convert.ToInt32(probabilidad_1 * num_pasajeros / 100) + 2 * Convert.ToInt32(probabilidad_2 * num_pasajeros / 100) + _2amas * Convert.ToInt32(probabilidad_2amas * num_pasajeros / 100);
            return carga;
        }

        private int calcular_pasajeros()
        {
            List<int> pasajeros = new List<int>();
            pasajeros.Add(250);
            pasajeros.Add(235);
            pasajeros.Add(210);
            pasajeros.Add(205);
            pasajeros.Add(200);
            pasajeros.Add(180);
            pasajeros.Add(150);
            pasajeros.Add(135);
            pasajeros.Add(120);
            pasajeros.Add(100);
            pasajeros.Add(90);

            List<int> porcentajes = new List<int>();
            porcentajes.Add(99);
            porcentajes.Add(96);
            porcentajes.Add(90);
            porcentajes.Add(87);
            porcentajes.Add(82);
            porcentajes.Add(80);
            porcentajes.Add(78);
            porcentajes.Add(75);
            porcentajes.Add(73);
            List<int> resultado1 = new List<int>();
            List<int> resultado2 = new List<int>();
            resultado1 = Shuffle(porcentajes);
            resultado2 = Shuffle(pasajeros);

            int porcentaje = resultado1.ElementAt(0);
            int pasajero = resultado2.ElementAt(0);         
            return Convert.ToInt32(pasajero * porcentaje / 100);

        }

        private List<int> Shuffle(List<int> input)
        {
            List<int> arr = input;
            List<int> arrDes = new List<int>();

            
            while (arr.Count > 0)
            {
                int val = randNum.Next(0, arr.Count - 1);
                arrDes.Add(arr[val]);
                arr.RemoveAt(val);
            }

            return arrDes; 
        }

        public DateTime UnixTimeStampToDateTime(double unixTimeStamp)
        {
            // Unix timestamp is seconds past epoch
            System.DateTime dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
            dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
            return dtDateTime;
        }

        public List<Vuelo> getMasDetalles()
        {
            List<Vuelo> listaVuelos = new List<Vuelo>();
            var db = new Bd_tesisDataContext();
            var query = (from v in db.Vuelo
                         orderby v.fecha_salida descending, v.hora_salida descending
                         select v);

            listaVuelos = query.ToList();
            return listaVuelos;
        }

        public List<Appointment> obtenerCitasDeVuelos()
        {
            List<Appointment> listaCitas = new List<Appointment>();
            List<Vuelo> listaVuelos = new List<Vuelo>();
            var db = new Bd_tesisDataContext();
            var query = (from v in db.Vuelo
                         select v);

            listaVuelos = query.ToList();

            foreach (Vuelo v in listaVuelos) 
            {
                DateTime fecha_llegada = Convert.ToDateTime(v.fecha_llegada).Add(TimeSpan.Parse(v.hora_llegada));
                DateTime fecha_salida = v.fecha_salida.Add(TimeSpan.Parse(v.hora_salida));
                string resumen = "Vuelo: " + v.num_vuelo;                               

                resumen = resumen.Replace("\n", Environment.NewLine);

                Appointment a = new Appointment(fecha_salida, fecha_llegada, resumen);

                if (v.estado == "Atendido")
                {
                    a.StatusId = (int)AppointmentStatus.Busy; 
                }
                else if (v.estado == "Cancelado")
                {
                    a.StatusId = (int)AppointmentStatus.Unavailable; 
                }
                else if (v.estado == "En Proceso")
                {
                    a.StatusId = (int)AppointmentStatus.Tentative; 
                }
                else if (v.estado == "En Espera")
                {
                    a.StatusId = (int)AppointmentStatus.Free; 
                }

                a.ResourceId = new EventId(v.perfil_personal_id);

                listaCitas.Add(a);
                
            }

            return listaCitas;
        }

        public List<Vuelo> obtenerVuelosXDia(DateTime dia) 
        {
            var db = new Bd_tesisDataContext();
            
            var query = (from v in db.Vuelo
                         where DateTime.Compare(v.fecha_salida, dia) == 0 && v.estado == "En Espera"
                         orderby v.fecha_salida ascending, v.hora_salida ascending
                         select v);         

            return query.ToList();
        }

        public List<Vuelo> obtenerVuelosRangoFechas(DateTime fecha_inicio, DateTime fecha_fin)
        {
            var db = new Bd_tesisDataContext();
            List<Vuelo> listaVuelo = new List<Vuelo>();

            try
            {
                var query = from v in db.Vuelo
                            where v.fecha_salida >= fecha_inicio && v.fecha_salida <= fecha_fin
                            select v;
                listaVuelo = query.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            return listaVuelo;
        }

        public void actualizarEstadoVuelos(List<Vuelo> listaVueloResultadoAlgoritmo)
        {
            var db = new Bd_tesisDataContext();
            List<Vuelo> listaVuelo = new List<Vuelo>();
            List<int> listaVueloIds = new List<int>();

            foreach (Vuelo v in listaVueloResultadoAlgoritmo)
            {
                listaVueloIds.Add(v.id);
            }

            try
            {
                var query = from v in db.Vuelo
                            select v;

                query = query.Where(v => listaVueloIds.Contains(v.id));

                listaVuelo = query.ToList();

                foreach (Vuelo vuelo in listaVuelo)
                {
                    vuelo.estado = listaVueloResultadoAlgoritmo.Where(v => v.id == vuelo.id).First().estado;
                }

                db.SubmitChanges();

            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public List<Vuelo> obtenerVuelos(FiltroVuelo filtroVuelo)
        {
            var db = new Bd_tesisDataContext();
            List<Vuelo> listaVuelo = new List<Vuelo>();

            try
            {
                var query = from v in db.Vuelo
                            where v.fecha_salida >= filtroVuelo.fecha_inicio && v.fecha_salida <= filtroVuelo.fecha_fin && v.PerfilPersonal == null
                            select v;

                if (filtroVuelo.turno > 0) 
                {
                    string inicio_horario;
                    string fin_horario;
                    switch (filtroVuelo.turno)
                    { 
                        case 1:
                            inicio_horario = new TimeSpan(0, 0, 0).ToString();
                            fin_horario = new TimeSpan(7, 59, 59).ToString();
                            query = query.Where(c => c.hora_salida.CompareTo(inicio_horario) >= 0 && c.hora_salida.CompareTo(fin_horario) <= 0);
                            break;
                        case 2:
                            inicio_horario = new TimeSpan(8, 0, 0).ToString();
                            fin_horario = new TimeSpan(15, 59, 59).ToString();
                            query = query.Where(c => c.hora_salida.CompareTo(inicio_horario) >= 0 && c.hora_salida.CompareTo(fin_horario) <= 0);
                            break;
                        case 3:
                            inicio_horario = new TimeSpan(16, 0, 0).ToString();
                            fin_horario = new TimeSpan(23, 59, 59).ToString();
                            query = query.Where(c => c.hora_salida.CompareTo(inicio_horario) >= 0 && c.hora_salida.CompareTo(fin_horario) <= 0);
                            break;
                    }
                }

                if (!String.IsNullOrEmpty(filtroVuelo.vuelo))
                {
                    query = query.Where(c => c.num_vuelo.Contains(filtroVuelo.vuelo));
                }

                listaVuelo = query.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            return listaVuelo;
        }

        public void cancelarVuelo(int vuelo_id_seleccionado)
        {
            var db = new Bd_tesisDataContext();

            try
            {
                var query = from v in db.Vuelo
                            where v.id == vuelo_id_seleccionado
                            select v;
                Vuelo vuelo = query.First();
                vuelo.estado = "Cancelado";

                db.SubmitChanges();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public bool ingresarVuelo(Vuelo vuelo)
        {
            var db = new Bd_tesisDataContext();
            bool resultado = false;
            try
            {
                db.Vuelo.InsertOnSubmit(vuelo);
                db.SubmitChanges();
                resultado = true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            return resultado;
        }

        public Vuelo obtenerVueloxId(int vuelo_id)
        {
            var db = new Bd_tesisDataContext();
            Vuelo vuelo = new Vuelo();
            try
            {
                var query = from v in db.Vuelo
                            where v.id == vuelo_id
                            select v;

                vuelo = query.First();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            return vuelo;
        }

        public bool actualizarVuelo(int vuelo_id, string num_vuelo, string tipo_avion, string tipo_vuelo, DateTime fecha_salida, DateTime fecha_llegada, string hora_salida, string hora_llegada, string nombre_aeropuerto, string origen, string destino, int pasajeros, double equipajes)
        {
            var db = new Bd_tesisDataContext();            
            bool resultado = false;

            try
            {
                var query = from v in db.Vuelo
                            where v.id == vuelo_id
                            select v;

                Vuelo vuelo = query.First();

                vuelo.num_vuelo = num_vuelo;
                vuelo.Tipo_avion = tipo_avion;
                vuelo.tipo_vuelo = tipo_vuelo;
                vuelo.fecha_salida = fecha_salida;
                vuelo.fecha_llegada = fecha_llegada;
                vuelo.hora_salida = hora_salida;
                vuelo.hora_llegada = hora_llegada;
                vuelo.nombre_aeropuerto = nombre_aeropuerto;
                vuelo.nombre_origen = origen;
                vuelo.nombre_destino = destino;
                vuelo.carga = equipajes;
                vuelo.num_pasajeros = pasajeros;

                db.SubmitChanges();
                resultado = true;
                
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            return resultado;
        }

        public List<Vuelo> buscarVuelosPendientes(DateTime fecha)
        {
            var db = new Bd_tesisDataContext();
            List<Vuelo> listaVuelo = new List<Vuelo>();
            try
            {
                var query = from v in db.Vuelo
                            where v.estado == "Pendiente" && v.fecha_salida.CompareTo(fecha) == 0
                            select v;

                listaVuelo = query.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            return listaVuelo;
        }

        public void aprobarVuelo(int vuelo_id)
        {
            var db = new Bd_tesisDataContext();
            try
            {
                var query = from v in db.Vuelo
                            where v.id == vuelo_id
                            select v;
                Vuelo vuelo = query.First();
                vuelo.estado = "En Espera";
                db.SubmitChanges();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public void aprobarVuelos(List<int> listaVueloIds)
        {
            var db = new Bd_tesisDataContext();
            try
            {
                var query = from v in db.Vuelo
                            select v;

                query = query.Where(v => listaVueloIds.Contains(v.id));

                List<Vuelo> listaVuelo = query.ToList();

                foreach (Vuelo v in listaVuelo)
                {
                    v.estado = "En Espera";
                }

                db.SubmitChanges();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public List<Vuelo> obtenerVuelosAsignadosAprobados(DateTime inicio, DateTime fin, string usuario)
        {
            var db = new Bd_tesisDataContext();
            List<Vuelo> listaVuelos = new List<Vuelo>();
            try
            {
                var query = from v in db.Vuelo
                            where v.fecha_salida >= inicio && v.fecha_salida <= fin && v.PerfilPersonal != null && v.aprobado == "Si"
                            select v;

                if (!String.IsNullOrEmpty(usuario))
                {
                    query = query.Where(c => c.PerfilPersonal.Usuario.nombre_usuario.StartsWith(usuario));
                }

                listaVuelos = query.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            return listaVuelos;
        }

        public List<Vuelo> obtenerVuelosAsignadosNoAprobados(DateTime fecha)
        {
            var db = new Bd_tesisDataContext();
            List<Vuelo> listaVuelos = new List<Vuelo>();
            try
            {
                var query = from v in db.Vuelo
                            where v.PerfilPersonal != null && v.aprobado == "No" && v.fecha_salida.CompareTo(fecha) == 0
                            select v;

                listaVuelos = query.ToList();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            return listaVuelos;
        }

        public bool asignarVuelos(int usuario_id, List<int> listaVueloIds)
        {
            var db = new Bd_tesisDataContext();
            bool resultado = false;

            try
            {
                var query = from p in db.PerfilPersonal
                            where p.Usuario.id == usuario_id
                            select p;

                int personal_id = query.First().id;

                var query2 = from v in db.Vuelo
                             where listaVueloIds.Contains(v.id)
                             select v;

                List<Vuelo> listaVuelo = query2.ToList();
                listaVuelo.ForEach(v => v.perfil_personal_id = personal_id);

                db.SubmitChanges();

                resultado = true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }

            return resultado;
        }

        public void desasignarVuelo(int vuelo_id_seleccionado)
        {
            var db = new Bd_tesisDataContext();

            try
            {

                var query = from v in db.Vuelo
                             where v.id == vuelo_id_seleccionado
                             select v;

                Vuelo vuelo = query.First();
                vuelo.PerfilPersonal = null;

                db.SubmitChanges();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public void aprobarVueloAsignado(int vuelo_id)
        {
            var db = new Bd_tesisDataContext();
            try
            {
                var query = from v in db.Vuelo
                            where v.id == vuelo_id
                            select v;

                Vuelo vuelo = query.First();

                vuelo.aprobado = "Si";
                db.SubmitChanges();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public void aprobarVuelosAsignados(List<int> listaVueloIds)
        {
            var db = new Bd_tesisDataContext();
            try
            {
                var query = from v in db.Vuelo
                            select v;

                query = query.Where(v => listaVueloIds.Contains(v.id));

                List<Vuelo> listaVuelo = query.ToList();

                foreach (Vuelo v in listaVuelo)
                {
                    v.aprobado = "Si";
                }

                db.SubmitChanges();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public void agregarVuelosDeCSV(List<Vuelo> listaVuelo)
        {
            var db = new Bd_tesisDataContext();

            try
            {
                db.Vuelo.InsertAllOnSubmit(listaVuelo);
                db.SubmitChanges();                
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}

